/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model.graphic.objects;

import controller.Constants;
import controller.commands.AddConnectionCommand;
import controller.commands.AddAttachmentCommand;
import controller.commands.DeleteCommand;
import controller.commands.SetHighlightColorCommand;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.geom.Arc2D;
import javax.swing.JOptionPane;
import model.graphic.locations.FlexibleRelativeLocation;
import view.GUI.LabelReader;
import view.GUI.graphic.GraphicView;

/**
 *
 * @author Jelle , modified by Ben
 */
public class GDispatcher extends AbstractHandle {

    private Arc2D arc;
    private int xdiff = 20;
    private int ydiff = 0;
    private int yp;
    private GSine line;//Line2D line;
    protected Polygon polygon;
    private Constants cons = new Constants();
    private Color oldColor = Color.RED;

    public GDispatcher() {
    }

    public GDispatcher(Attachment baseHandle) {
        super(baseHandle, new FlexibleRelativeLocation(((RectangleAttachment) baseHandle).getUpperRight(), 0, 0));

        int xx = ((RectangleAttachment) base).getUpperRight().getX() + xdiff;
        int yy = ((RectangleAttachment) base).getUpperRight().getY() + ydiff;
        arc = new Arc2D.Double(xx, yy - 5 + yp, 10, 10, 90, 180, Arc2D.OPEN);
        //line = new Line2D.Double(((RectangleAttachment) base).getUpperRight().getX(), ((RectangleAttachment) base).getUpperRight().getY() + yp, xx, yy + yp);
        line = new GSine(((RectangleAttachment) base).getUpperRight().getX(), ((RectangleAttachment) base).getUpperRight().getY() + yp, xx, yy + yp);
    }

    public void move(Attachment base) {
        adjustLocation(base, new FlexibleRelativeLocation(((RectangleAttachment) base).getUpperRight(), 0, 0));
    }

    public void paint(Graphics2D g) {
        if (this.isVisible() && (base.isVisible() || ((RectangleAttachment)base).isCollapsed() ) && ((Attachment)base).getBase().isVisible()) {
            Graphics2D g2 = (Graphics2D) g;
            Color oldColor = g.getColor();
            Stroke oldStroke = g.getStroke();

            Stroke lineStroke = cons.getDashedStroke();
            Stroke arcStroke = oldStroke;

            if (highlighted) {
                g.setColor(getHighlightColor());
                lineStroke = cons.getDashedBoldStroke();
                arcStroke = new BasicStroke(2.0f);
            }else if (selected) {
                g.setColor(getHighlightColor());
            } else {
                g.setColor(getBaseColor());
            }

            g.setStroke(lineStroke);
            yp = 15 / 2;
            int xx = ((RectangleAttachment) base).getUpperRight().getX() + xdiff;
            int yy = ((RectangleAttachment) base).getUpperRight().getY() + ydiff;
            line = new GSine(((RectangleAttachment) base).getUpperRight().getX(), ((RectangleAttachment) base).getUpperRight().getY() + yp, xx, yy + yp);
            line.paint(g);//g.draw(line);

            g.setStroke(arcStroke);
            arc = new Arc2D.Double(xx, yy - 5 + yp, 10, 10, 90, 180, Arc2D.OPEN);
            g2.draw(arc);

            g.setColor(oldColor);
            g.setStroke(oldStroke);
        }
    }

    @Override
    public boolean contains(int x, int y) {
        boolean isIn = false;
        createPolygon();
        if (polygon.contains(x + this.getX(), y + this.getY())) {
            isIn = true;
        }
        if (arc.contains(x + this.getX(), y + this.getY())) {
            isIn = true;
        }
        return isIn;
    }

    public void adjustLine(int x, int y) {
        int terug = ((GDispatcherPort) getBase()).getWidth();
        xdiff = x - ((Attachment) getBase()).getGraphLocation().getX() - terug;
        ydiff = y - ((Attachment) getBase()).getGraphLocation().getY() - 15 / 2;
    }

    public void createPolygon() {
        polygon = new Polygon();
        polygon.addPoint((int) line.getX1(), (int) line.getY1() + 8);
        polygon.addPoint((int) line.getX2(), (int) line.getY2() + 8);
        polygon.addPoint((int) line.getX2(), (int) line.getY2() - 8);
        polygon.addPoint((int) line.getX1(), (int) line.getY1() - 8);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        GraphicView gv = (GraphicView) this.getParent();
        gv.setLayer(this, 10, -1);
        this.adjustLine(e.getX() + this.getX(), e.getY() + this.getY());
        this.setHighlighted(true);
        if (gv.getTriggerFound() != null) {
            gv.notifyObservers(new SetHighlightColorCommand(Color.GREEN, this));
        } else {
            gv.notifyObservers(new SetHighlightColorCommand(oldColor, this));
        }
        gv.repaint();
    }

    @Override
    public void mousePressed(MouseEvent e) {
        this.dragStartPoint = e.getPoint();
        this.dragEndPoint = e.getPoint();
        oldColor = this.getHighlightColor();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        this.setHighlighted(false);
        GraphicView gv = (GraphicView) this.getParent();
        if (gv.getTriggerFound() != null) {
            GDispatcherPort dp = (GDispatcherPort) this.getBase();
            if (GTransmitterNode.class.isAssignableFrom(dp.getBase().getClass())
            && GTransmitterNode.class.isAssignableFrom(((GTriggerPort) gv.getTriggerFound().getBase()).getBase().getClass())) {
                GTransmitterNode t1 = (GTransmitterNode) dp.getBase();
                GTransmitterNode t2 = (GTransmitterNode) ((GTriggerPort) gv.getTriggerFound().getBase()).getBase();
                if (t1.getBase() != t2.getBase()) {
                    gv.notifyObservers(new AddConnectionCommand(dp, gv.getTriggerFound(), this, gv.getRootPane().getLayeredPane()));
                    gv.notifyObservers(new DeleteCommand(this));
                    gv.notifyObservers(new AddAttachmentCommand(Constants.getDispatcherString(), dp));
                } else {
                    JOptionPane.showMessageDialog(gv.getParent(), LabelReader.getInstance().getString("InputOutputSameParentnode"), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                    gv.notifyObservers(new DeleteCommand(this));
                    gv.notifyObservers(new AddAttachmentCommand(Constants.getDispatcherString(), dp));
                }
            } else if (dp.getBase() != ((GTriggerPort) gv.getTriggerFound().getBase()).getBase()) {
                gv.notifyObservers(new AddConnectionCommand(dp, gv.getTriggerFound(), this, gv.getRootPane().getLayeredPane()));
                gv.notifyObservers(new DeleteCommand(this));
                gv.notifyObservers(new AddAttachmentCommand(Constants.getDispatcherString(), dp));
            } else {
                JOptionPane.showMessageDialog(gv.getParent(), LabelReader.getInstance().getString("InputOutputSameParentnode"), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                gv.notifyObservers(new DeleteCommand(this));
                gv.notifyObservers(new AddAttachmentCommand(Constants.getDispatcherString(), dp));
            }
        }
    }
}
